package com.hunan.api.catv.service.biz.subscribe;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.hunan.api.catv.common.CacheKey;
import com.hunan.api.catv.entity.ServiceResult;
import com.hunan.api.catv.entity.enums.ColumnEnum;
import com.hunan.api.catv.entity.vo.ActivityVo;
import com.hunan.api.catv.entity.vo.LiveVo;
import com.hunan.api.catv.mq.MqConstants;
import com.hunan.api.catv.service.ResultService;
import com.hunan.api.catv.service.biz.cache.CacheBiz;
import com.hunan.api.catv.service.biz.live.LiveBiz;
import com.hunan.api.catv.service.biz.mq.MqBiz;
import com.hunan.api.catv.utils.GsonUtils;
import com.hunan.api.catv.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

@Service
public class SubscribeBiz extends ResultService {

    @Autowired
    MqBiz mqBiz;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    CacheBiz cacheBiz;

    @Autowired
    LiveBiz liveBiz;

    public ServiceResult submit(Integer flag, Integer memberId, Integer contentType, String content) {
        JsonObject msg = new JsonObject();
        msg.addProperty("flag", flag);
        msg.addProperty("memberId", memberId);
        msg.addProperty("contentType", contentType);
        msg.addProperty("content", content);
        mqBiz.push(MqConstants.subscribe_exchange, MqConstants.subscribe_routingkey, GsonUtils.toJson(msg));
        return buildOK(true, flag == 1 ? "预约成功" : "取消预约成功");
    }

    public void save(Integer memberId, Integer contentType, String content) {
        Long expire = 0L;
        Long nowSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        Long startTime = 0L;
        String contentId = content;
        if (ColumnEnum.activity.getCode().equals(contentType)) {
            ActivityVo activityVo = cacheBiz.activityInfoCache(Integer.valueOf(content));
            if (!ObjectUtils.isEmpty(activityVo)) {
                startTime = activityVo.getStartTime();
            }
        }
        if (ColumnEnum.tv.getCode().equals(contentType)) {
            JsonObject schedule = GsonUtils.fromJson(content, JsonObject.class);
            startTime = LocalDateTime.parse(schedule.get("startTime").getAsString(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")).toEpochSecond(ZoneOffset.of("+8"));
            contentId = schedule.get("scheduleId").getAsString();
        }
        if (ColumnEnum.live.getCode().equals(contentType)) {
            LiveVo liveVo = cacheBiz.liveInfo(Integer.valueOf(content));
            if (!ObjectUtils.isEmpty(liveVo)) {
                startTime = liveVo.getStartTime();
            }
        }
        expire = startTime - nowSecond;
        String memberSubscribeKey = MessageFormat.format(CacheKey.member_subscribe_record, memberId, contentType);
        String contentSubscribeKey = MessageFormat.format(CacheKey.content_subscribe_record, contentId, contentType);
        if (expire > 0) {
            Long preExpire = redisUtils.getExpire(memberSubscribeKey);
            redisUtils.sSetAndTime(memberSubscribeKey, preExpire > expire ? preExpire : expire, content);
            redisUtils.sSetAndTime(contentSubscribeKey, expire, memberId);
            createTask(contentType, content, expire);
        }
    }

    public void cancel(Integer memberId, Integer contentType, String content) {
        JsonArray array = GsonUtils.fromJson(content, JsonArray.class);
        String memberSubscribeKey = MessageFormat.format(CacheKey.member_subscribe_record, memberId, contentType);
        for (JsonElement contentId : array) {
            if (ColumnEnum.tv.getCode().equals(contentType)) {
                JsonObject schedule = GsonUtils.fromJson(contentId.toString(), JsonObject.class);
                Set<Object> memberSubscribeValue = redisUtils.sGet(memberSubscribeKey);
                for (Object repertoire : memberSubscribeValue) {
                    JsonObject repertoires = GsonUtils.fromJson(repertoire.toString(), JsonObject.class);
                    if (schedule.get("scheduleId").equals(repertoires.get("scheduleId"))) {
                        redisUtils.setRemove(memberSubscribeKey, repertoire);
                        contentId = GsonUtils.fromJson(schedule.get("scheduleId").getAsString(), JsonElement.class);
                    }
                }
            } else {
                contentId = GsonUtils.fromJson(contentId.getAsString(), JsonElement.class);
                redisUtils.setRemove(memberSubscribeKey, contentId.getAsString());
            }
            String contentSubscribeKey = MessageFormat.format(CacheKey.content_subscribe_record, contentId.getAsString(), contentType);
            redisUtils.setRemove(contentSubscribeKey, memberId);
        }

    }

    public List<Object> list(Integer memberId, Integer contentType) {
        Long nowSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        Long endTime = 0L;
        String memberSubscribeKey = MessageFormat.format(CacheKey.member_subscribe_record, memberId, contentType);
        Set<Object> set = redisUtils.sGet(memberSubscribeKey);
        List<Object> list = new LinkedList<Object>();
        if (!ObjectUtils.isEmpty(set)) {
            if (contentType.equals(ColumnEnum.tv.getCode())) {
                for (Object o : set) {
                    JsonObject schedule = GsonUtils.fromJson(o.toString(), JsonObject.class);
                    if (!ObjectUtils.isEmpty(schedule)) {
                        endTime = LocalDateTime.parse(schedule.get("endTime").getAsString(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")).toEpochSecond(ZoneOffset.of("+8"));
                        if (endTime < nowSecond) {
                            redisUtils.setRemove(memberSubscribeKey, o);
                            continue;
                        } else {
                            list.add(schedule);
                        }
                    }
                }
            }
            if (contentType.equals(ColumnEnum.live.getCode())) {
                for (Object o : list) {
                    Integer contentId = Integer.valueOf(o.toString());
                    LiveVo live = cacheBiz.liveInfo(contentId);
                    if (!ObjectUtils.isEmpty(live) && 1 == live.getState()) {
                        endTime = live.getEndTime();
                        if (endTime < nowSecond) {
                            redisUtils.setRemove(memberSubscribeKey, o);
                            continue;
                        } else {
                            list.add(live);
                        }
                    }
                }
            }
            if (contentType.equals(ColumnEnum.activity.getCode())) {
                for (Object o : list) {
                    Integer contentId = Integer.valueOf(o.toString());
                    ActivityVo activityVo = cacheBiz.activityInfoCache(contentId);
                    if (!ObjectUtils.isEmpty(activityVo) && 1 == activityVo.getState()) {
                        endTime = activityVo.getEndTime();
                        if (endTime < nowSecond) {
                            redisUtils.setRemove(memberSubscribeKey, o);
                            continue;
                        } else {
                            list.add(activityVo);
                        }
                    }
                }
            }
        }
        return list;
    }

    public JsonObject query(Integer memberId, Integer contentType, String content) {
        JsonObject result = new JsonObject();
        String memberSubscribeKey = MessageFormat.format(CacheKey.member_subscribe_record, memberId, contentType);
        boolean flag = redisUtils.sHasKey(memberSubscribeKey, content);
        if (ColumnEnum.tv.getCode().equals(contentType)) {
            //JsonObject schedule = GsonUtils.fromJson(content, JsonObject.class);
            //content = schedule.get("scheduleId").getAsString();
            Set<Object> memberSubscribeValue = redisUtils.sGet(memberSubscribeKey);
            for (Object repertoire : memberSubscribeValue) {
                JsonObject schedule = GsonUtils.fromJson(repertoire.toString(), JsonObject.class);
                String scheduleId = schedule.get("scheduleId").getAsString();
                if (content.equals(scheduleId)) {
                    flag = true;
                }
            }
        }
        String contentSubscribeKey = MessageFormat.format(CacheKey.content_subscribe_record, content, contentType);
        Long count = redisUtils.sGetSetSize(contentSubscribeKey);
        result.addProperty("status", flag);
        result.addProperty("count", count);
        return result;
    }

    public List<Object> queryAllSubscribe(Integer memberId, Integer contentType, String content) {
        String memberSubscribeKey = MessageFormat.format(CacheKey.member_subscribe_record, memberId, contentType);
        Set<Object> set = redisUtils.sGet(memberSubscribeKey);
        List<Object> list = new LinkedList<Object>();
        if (!ObjectUtils.isEmpty(set)) {
            Iterator<Object> it = set.iterator();
            if (contentType.equals(ColumnEnum.tv.getCode())) {
                while (it.hasNext()) {
                    JsonObject schedule = GsonUtils.fromJson(it.next().toString(), JsonObject.class);
                    if (!ObjectUtils.isEmpty(schedule) && content.equals(schedule.get("channelId").getAsString())) {
                        list.add(schedule.get("scheduleId").getAsString());
                    }
                }
            } else {
                while (it.hasNext()) {
                    list.add(it.next());
                }
            }
        }
        return list;

    }

    public void createTask(Integer contentType, String content, Long delayTime) {
        String contentId = content;
        if (ColumnEnum.tv.getCode().equals(contentType)) {
            JsonObject schedule = GsonUtils.fromJson(content, JsonObject.class);
            contentId = schedule.get("scheduleId").getAsString();
        }
        String contentSubscribeKey = MessageFormat.format(CacheKey.content_subscribe_record, contentId, contentType);
        Set<Object> set = redisUtils.sGet(contentSubscribeKey);
        if (set.size() == 1) {
            JsonObject msg = new JsonObject();
            msg.addProperty("contentType", contentType);
            msg.addProperty("content", content);
            if (delayTime > 300) {
                delayTime = delayTime - 300;
            }
            mqBiz.delayPush(MqConstants.subscribe_notify_exchange, MqConstants.subscribe_notify_routingkey, GsonUtils.toJson(msg), delayTime * 1000L);
        }
    }

}
